home *** CD-ROM | disk | FTP | other *** search
/ MacTech 1 to 12 / MacTech-vol-1-12.toast / Source / MacTech® Magazine / Volume 11 - 1995 / 11.07 Jul 95 / 11.07 ProgChall - hyphen.c / hyphen.c
Encoding:
C/C++ Source or Header  |  1995-05-14  |  4.5 KB  |  134 lines  |  [TEXT/KAHL]

  1.  
  2. /*                     HY-PHEN-A-TION                     */
  3. /*                                                        */
  4. /*                   Raffi J. Kasparian                   */
  5. /*                                                        */
  6. /* Please set the following three defines to appropriate  */
  7. /* values if their default settings are not appropriate.  */
  8.  
  9. #define AllowMixedCaseDoubleConsonants                  true
  10. /* if, for example, "Ss" or "sS" might occur in the       */
  11. /* middle of the word (as in "paSsion").                  */
  12.  
  13. #define AllowZeroLengthWords                           false
  14. /* if the length byte might be a zero.                    */
  15.  
  16. #define AllowMultipleConsonants                         true
  17. /* if multiple ( >2 ) same-consonants are po"sssss"ible.  */
  18.  
  19. #define uchar unsigned char
  20. #define ulong unsigned long
  21. #define kHyphen 0x2D
  22. #define v( a ) ( a == 'A' || a == 'a' || \
  23.                  a == 'E' || a == 'e' || \
  24.                  a == 'I' || a == 'i' || \
  25.                  a == 'O' || a == 'o' || \
  26.                  a == 'U' || a == 'u' )
  27.  
  28. static Boolean vowelTable[128] = {
  29.   v(0), v(1), v(2), v(3), v(4), v(5), v(6), v(7), v(8), 
  30.   v(9), v(10), v(11), v(12), v(13), v(14), v(15), v(16), 
  31.   v(17), v(18), v(19), v(20), v(21), v(22), v(23), v(24), 
  32.   v(25), v(26), v(27), v(28), v(29), v(30), v(31), v(32), 
  33.   v(33), v(34), v(35), v(36), v(37), v(38), v(39), v(40), 
  34.   v(41), v(42), v(43), v(44), v(45), v(46), v(47), v(48), 
  35.   v(49), v(50), v(51), v(52), v(53), v(54), v(55), v(56), 
  36.   v(57), v(58), v(59), v(60), v(61), v(62), v(63), v(64), 
  37.   v(65), v(66), v(67), v(68), v(69), v(70), v(71), v(72), 
  38.   v(73), v(74), v(75), v(76), v(77), v(78), v(79), v(80), 
  39.   v(81), v(82), v(83), v(84), v(85), v(86), v(87), v(88), 
  40.   v(89), v(90), v(91), v(92), v(93), v(94), v(95), v(96), 
  41.   v(97), v(98), v(99), v(100), v(101), v(102), v(103), 
  42.   v(104), v(105), v(106), v(107), v(108), v(109), v(110), 
  43.   v(111), v(112), v(113), v(114), v(115), v(116), v(117), 
  44.   v(118), v(119), v(120), v(121), v(122), v(123), v(124), 
  45.   v(125), v(126), v(127)
  46. };
  47.  
  48. void *InitHyphenation( ulong maxRAM )
  49. {
  50.   return (void*)vowelTable;
  51. }
  52.  
  53. void Hyphenate( privateDataPtr, inPtr, outPtr )
  54.   void *privateDataPtr;
  55.   Str255 *inPtr;
  56.   Str255 *outPtr;
  57. {
  58.   #define mIsVowel( a ) ( ((Boolean*)privateDataPtr)[a] )
  59.   #define mIsConsonant( a ) ( ! mIsVowel( a ) )
  60.  
  61.   #if AllowMixedCaseDoubleConsonants
  62.     #define mIsDoubleConsonant( in )\
  63.       ( *in == ( a = *( in + 1 ) ) || *in == a + 'a' - 'A' \
  64.         || *in == a + 'A' - 'a' )
  65.   #else
  66.     #define mIsDoubleConsonant( in ) ( *in == *( in + 1 ) )
  67.   #endif
  68.   
  69.   register uchar *in, *out, *out0, *inLast, *lastVowel;
  70.   #if AllowMixedCaseDoubleConsonants
  71.     register uchar a;
  72.   #endif
  73.   
  74.   in = *inPtr;
  75.   out = out0 = *outPtr;
  76.   lastVowel = inLast = in + *in;
  77.  
  78.   /* working from back to front of the word, locate the   */
  79.   /* last vowel not including final 'e', 'es', or 'ed.    */
  80.   if( mIsVowel( *lastVowel ) ){
  81.     if( *lastVowel == 'e' || *lastVowel == 'E' ){
  82.       lastVowel--;
  83.       goto FIND_LAST_VOWEL;
  84.     }
  85.     else goto ALGORITHM;
  86.   }
  87.   switch( *lastVowel-- ){
  88.   case 's': case 'd': case 'S': case 'D':
  89.     if( *lastVowel == 'e' || *lastVowel == 'E' )
  90.       lastVowel--;
  91.     break;
  92.   #if AllowZeroLengthWords
  93.     case '\0': goto COPY_TO_END;
  94.   #endif
  95.   }  
  96.   FIND_LAST_VOWEL: do{
  97.     if( lastVowel == in ) goto COPY_TO_END;
  98.     if( mIsVowel( *lastVowel ) ) break;
  99.     lastVowel--;
  100.   }while( true );
  101.  
  102.   ALGORITHM:  
  103.   /* Working forwards from the beginning of the word      */
  104.   /* until lastVowel is reached, hyphenate every          */
  105.   /* vowel/consonant pair unless the vowel is followed by */
  106.   /* a double consonant.  In this case, hyphenate between */
  107.   /* the double consonant.  This method meets the         */
  108.   /* hyphenation requirements without having to deal      */
  109.   /* directly with all the letter combination rules.      */
  110.   
  111.   *out++ = *in++; /* copy length byte */
  112.   while( true ){
  113.     while( mIsConsonant( *in ) )
  114.       *out++ = *in++;                    
  115.     do{
  116.       if( in == lastVowel ) goto COPY_TO_END;
  117.       *out++ = *in++;        
  118.     }while( mIsVowel( *in ) );    
  119.     
  120.     /* handle double or multiple consonants               */
  121.     #if AllowMultipleConsonants
  122.       while( mIsDoubleConsonant( in ) ) *out++ = *in++;
  123.     #else
  124.       if( mIsDoubleConsonant( in ) ) *out++ = *in++;
  125.     #endif       
  126.     *out++ = kHyphen; *out++ = *in++; (*out0)++;
  127.   }
  128.   COPY_TO_END: do *out++ = *in++; while( in <= inLast );
  129.   
  130. #undef mIsVowel
  131. #undef mIsConsonant
  132. #undef mIsDoubleConsonant
  133. }
  134.